package com.feature.shop.auth.service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.feature.core.constant.SecurityConstants;
import com.feature.core.domain.Response;
import com.feature.core.util.AssertUtil;
import com.feature.core.util.JwtUtils;
import com.feature.core.util.PasswordUtil;
import com.feature.shop.auth.api.cache.AuthCache;
import com.feature.shop.auth.api.constant.AuthMqConstatns;
import com.feature.shop.auth.api.vo.LoginUserVo;
import com.feature.shop.auth.model.request.LoginRequest;
import com.feature.shop.auth.model.vo.LoginVo;
import com.feature.shop.user.api.ShopUserApi;
import com.feature.shop.user.api.vo.ShopUserVo;

@Service
public class AuthService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    ShopUserApi shopUserApi;

    @Autowired
    RabbitTemplate rabbitTemplate;

    public LoginVo login(LoginRequest req, String ip) {
        JSON.config(JSONWriter.Feature.NotWriteDefaultValue);
        Response<ShopUserVo> userResp = shopUserApi.queryUserByName(req.getUsername());
        logger.info("AuthService.login-shopUserApi.queryUserByName，input:{},output:{}", req.getUsername(), JSON.toJSONString(userResp));
        AssertUtil.isTrue(userResp.isSuccess(), userResp.getCode(), userResp.getMsg());
        AssertUtil.isTrue(userResp.getData() != null, "用户名密码错误");
        ShopUserVo user = userResp.getData();
        // 校验密码
        boolean validPassword = PasswordUtil.validate(req.getPassword(), user.getPassword());
        AssertUtil.isTrue(validPassword, "用户名密码错误");
        return buildLoginVo(user, ip);
    }

    public LoginVo refreshToken(String refreshToken, String ip) {
        boolean isRefreshTokenExpire = AuthCache.hasRefreshToken(refreshToken);
        AssertUtil.isTrue(isRefreshTokenExpire, "refreshToken已过期，请重新登录");
        Integer userId = JwtUtils.getValue(refreshToken, SecurityConstants.USER_ID_KEY);
        AssertUtil.notNull(userId, "refreshToken无效");
        Response<ShopUserVo> userResp = shopUserApi.queryUserById(userId);
        logger.info("AuthService.refreshToken-shopUserApi.queryUserById，input:{},output:{}", userId, JSON.toJSONString(userResp));
        AssertUtil.isTrue(userResp.isSuccess(), userResp.getCode(), userResp.getMsg());
        ShopUserVo user = userResp.getData();
        return buildLoginVo(user, ip);
    }

    public void logout(String accessToken) {
        Integer userId = JwtUtils.getValue(accessToken, SecurityConstants.USER_ID_KEY);
        AssertUtil.notNull(userId, "accessToken无效");
        AuthCache.clearLoginUserInfo(userId);
        AuthCache.clearToken(accessToken);
    }

    public LoginVo buildLoginVo(ShopUserVo loginUser, String ip) {
        LoginVo loginVo = new LoginVo();
        // Jwt存储信息
        Map<String, Object> claimsMap = new HashMap<String, Object>();
        claimsMap.put(SecurityConstants.USER_ID_KEY, loginUser.getId());
        String token = JwtUtils.createToken(claimsMap);
        String refreshToken = JwtUtils.createToken(claimsMap);
        AuthCache.setAccessToken(token, SecurityConstants.ACCESS_TOKEN_EXPIRE_TIME);
        AuthCache.setRefreshToken(refreshToken, SecurityConstants.REFRESH_TOKEN_EXPIRE_TIME);
        loginVo.setAccessToken(token);
        loginVo.setExpires(DateUtils.addMilliseconds(new Date(), (int) SecurityConstants.ACCESS_TOKEN_EXPIRE_TIME));
        loginVo.setRefreshToken(refreshToken);
        loginVo.setRefreshTokenExpireTime(DateUtils.addMilliseconds(new Date(), (int) SecurityConstants.REFRESH_TOKEN_EXPIRE_TIME));
        loginVo.setAvatar(loginUser.getHeadImg());
        loginVo.setUsername(loginUser.getName());
        loginVo.setNickname(loginUser.getNickName());
        loginVo.setPermissions(loginUser.getPermissions());
        loginVo.setRoles(loginUser.getRoles());
        LoginUserVo loginUserVo = new LoginUserVo();
        loginUserVo.setIpaddr(ip);
        loginUserVo.setLoginTime(new Date());
        loginUserVo.setUser(loginUser);
        AuthCache.setLoginUserInfo(loginUserVo, SecurityConstants.USER_EXPIRE_TIME);
        rabbitTemplate.convertAndSend(AuthMqConstatns.SHOP_LOGIN_SUCCESS_EXCHANGE, AuthMqConstatns.SHOP_LOGIN_SUCCESS_ROUTING_KEY, "{\"userName\":\"" + loginUser.getName() + "\"}");
        return loginVo;
    }
}
